package concurrency.juc;

import concurrency.LiftOff;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

/**
 * @author Mr.Sun
 * @date 2022年09月06日 9:25
 *
 * 生产者-消费者与队列
 */
public class TestBlockingQueues {

    public static void main(String[] args) {
        // 无界队列
        test("LinkedBlockingQueue", new LinkedBlockingQueue<>());

        // 有界队列
        test("ArrayBlockingQueue", new ArrayBlockingQueue<>(3));

        // 同步队列，容量大小为1
        test("SynchronousQueue", new SynchronousQueue<>());
    }

    static void test(String msg, BlockingQueue<LiftOff> queue) {
        System.out.println(msg);
        LiftOffRunner runner = new LiftOffRunner(queue);
        Thread t = new Thread(runner);
        t.start();
        for(int i = 0; i < 5; i++) {
            runner.add(new LiftOff(5));
        }

        getKey("Press 'Enter' (" + msg + ")");
        t.interrupt();
        System.out.println("Finished " + msg + " test");
    }

    static void getKey(String message) {
        System.out.println(message);
        getKey();
    }

    static void getKey() {
        try {
            // 补偿Windows/Linux中回车键产生的结果长度的差异
            new BufferedReader(new InputStreamReader(System.in)).readLine();
        } catch(java.io.IOException e) {
            throw new RuntimeException(e);
        }
    }
}

// 火箭发射任务
class LiftOffRunner implements Runnable {

    private BlockingQueue<LiftOff> rockets;

    public LiftOffRunner(BlockingQueue<LiftOff> queue) {
        this.rockets = queue;
    }

    public void add(LiftOff liftOff) {
        try {
            rockets.put(liftOff);
        } catch (InterruptedException e) {
            System.out.println("Interrupted for put()");
        }
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                LiftOff rocket = rockets.take();
                rocket.run(); // 使用LiftOff线程
            }
        } catch (InterruptedException e) {
            System.out.println("waking from take()");
        }
        System.out.println("Exiting LiftOffRunner");
    }
}
